# 对一副二值图像进行膨胀、腐蚀、开、闭操作，提取边缘；

"""
腐蚀
cv2.erode(src,                     # 输入图像
        kernel,                  # 卷积核
        dst=None,
        anchor=None,
        iterations=None,         # 迭代次数，默认1
        borderType=None,
        borderValue=None)
膨胀
cv2.dilate(src,                    # 输入图像
           kernel,                 # 卷积核
           dst=None,
           anchor=None,
           iterations=None,        # 迭代次数，默认1
           borderType=None,
           borderValue=None)
开、闭、梯度
cv2.morphologyEx(src,      # 输入图片
                 op,       # 需要处理类型的函数：(cv2.MORPH_OPEN,cv2.MORPH_CLOSE,cv2.MORPH_GRADIENT)
                 kernel,   # 卷积核大小
                 dst=None, 
                 anchor=None, 
                 iterations=None,     #迭代次数，默认1次
                 borderType=None, 
                 borderValue=None)
————————————————

"""
import cv2
import matplotlib.pyplot as plt

plt.rcParams['font.sans-serif'] = ['SimHei']  # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False  # 用来正常显示负号


# 二值化
def threshold_demo(image):
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    ret, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)
    # cv2.threshold第二个参数设定 红色通道阈值（阈值影响开闭运算效果）
    print("threshold value %s" % ret)
    # 显示
    # cv2.imshow("global_threshold_binary", binary)
    return binary


img = cv2.imread('img/lena.png')
# 对图像二值化处理
img = threshold_demo(img)

# OpenCV定义的结构矩形元素
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))

# 腐蚀图像
eroded = cv2.erode(img, kernel)

# 膨胀图像
dilated = cv2.dilate(img, kernel)

# cv2.imshow("img", img)
# cv2.imshow("Eroded", eroded)
# cv2.imshow("Dilated", dilated)
# cv2.waitKey(0)

plt.subplot(131), plt.imshow(img,'gray') ,plt.title("原图")
plt.subplot(132), plt.imshow(dilated,'gray'), plt.title("膨胀")
plt.subplot(133), plt.imshow(eroded,'gray'), plt.title("腐蚀")
plt.show()
# 闭运算 迭代次数不同
closed1 = cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel, iterations=1)
closed3 = cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel, iterations=3)
closed5 = cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel, iterations=5)
# 开运算
opened1 = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel, iterations=1)
opened3 = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel, iterations=3)
opened5 = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel, iterations=5)
# 梯度
# gradient = cv2.morphologyEx(img, cv2.MORPH_GRADIENT, kernel)

# 显示如下腐蚀后的图像
# cv2.imshow("Close1", closed1)
# cv2.imshow("Close3", closed3)
# cv2.imshow("Open1", opened1)
# cv2.imshow("Open3", opened3)
# cv2.imshow("gradient", gradient)
# cv2.waitKey(0)

plt.subplot(241), plt.imshow(img,'gray') ,plt.title("原图")
plt.subplot(242), plt.imshow(opened1,'gray'), plt.title("开运算iterations=1")
plt.subplot(243), plt.imshow(opened3,'gray'), plt.title("开运算iterations=3")
plt.subplot(244), plt.imshow(opened5,'gray'), plt.title("开运算iterations=5")
plt.subplot(246), plt.imshow(closed1,'gray'), plt.title("闭运算iterations=1")
plt.subplot(247), plt.imshow(closed3,'gray'), plt.title("闭运算iterations=3")
plt.subplot(248), plt.imshow(closed5,'gray'), plt.title("闭运算iterations=5")
plt.show()
# 将两幅图像相减获得边；cv2.absdiff参数：(膨胀后的图像，腐蚀后的图像)
absdiff_img = cv2.absdiff(dilated, eroded);
result = cv2.bitwise_not(absdiff_img);

# cv2.imshow("absdiff_img", absdiff_img)
# cv2.imshow("result", result)
# cv2.waitKey(0)

plt.subplot(131), plt.imshow(img,'gray') ,plt.title("原图")
plt.subplot(132), plt.imshow(absdiff_img,'gray'), plt.title("腐蚀、膨胀两幅图像相减")
plt.subplot(133), plt.imshow(result,'gray'), plt.title("提取边缘")
plt.show()
